package com.crawler.waf;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.EnumSet;

import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.crawler.waf.config.WafProperties;
import com.crawler.waf.filter.CorsFilter;
import com.crawler.waf.filter.ExceptionFilter;
import com.crawler.waf.filter.WafHttpMethodOverrideFilter;
import com.crawler.waf.support.Constants;

/**
 * web项目的启动配置 
 *
 */
@Order(1)
public abstract class AbstractWebBaseApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	protected boolean disableSecurity = false;// 关闭安全认证

	/**
	 * 配置servlet的映射路径
	 */
	@Override
	protected String[] getServletMappings() {

		return new String[] { "/" };
	}

	public boolean isDisableSecurity() {
		return this.disableSecurity;
	}

	/**
	 * 
	 * @Title: setDisableSecurity
	 * @Description: 是否关闭安全认证，默认为开启安全认证
	 * @param @param disableSecurity 设定文件
	 * @return void 返回类型
	 * @throws
	 */
	public void setDisableSecurity(boolean disableSecurity) {
		this.disableSecurity = disableSecurity;
	}
	

	/**
	 * 設置当spring没有找到Handler的时候，抛出NoHandlerFountException异常。并且被异常捕获到。统一进行处理
	 */
	@Override
	protected void customizeRegistration(Dynamic registration) {
		registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
	}

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.setProperty("http.maxConnections", "100");
		servletContext.setInitParameter(Constants.DISABLE_SECURITY,
				String.valueOf(this.isDisableSecurity()));// 设置安全认证全局开关，默认为开启安全认证
		
		super.onStartup(servletContext);

		initCharacterEncodingFilter(servletContext);
		initCorsFilter(servletContext);
		initHiddenHttpMethodFilter(servletContext);
		initExceptionFilter(servletContext);

		Writer result = new StringWriter();
		PrintWriter printWriter = new PrintWriter(result);
		WafProperties.getProperties().list(printWriter);
		logger.info(result.toString());
	}
	
	/**
	 * 
	* @Title: initCharacterEncodingFilter 
	* @Description:  字符编码过滤器
	* @param @param servletContext    设定文件 
	* @return void    返回类型 
	* @throws
	 */
	protected void initCharacterEncodingFilter(ServletContext servletContext) {
		CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
		characterEncodingFilter.setForceEncoding(true);
		characterEncodingFilter.setEncoding("UTF-8");
		FilterRegistration.Dynamic filterRegistration = servletContext.addFilter("characterEncodingFilter", characterEncodingFilter);
		filterRegistration.setAsyncSupported(isAsyncSupported());
		filterRegistration.addMappingForUrlPatterns(getDispatcherTypes(), false,  "/*");
	}
	

	protected void initHiddenHttpMethodFilter(ServletContext servletContext) {
		FilterRegistration.Dynamic wafHiddenHttpMethodFilter = servletContext.addFilter("wafHiddenHttpMethodFilter", new WafHttpMethodOverrideFilter());
		wafHiddenHttpMethodFilter.setAsyncSupported(isAsyncSupported());
		wafHiddenHttpMethodFilter.addMappingForUrlPatterns(getDispatcherTypes(), false,  "/*");
	}
	
	/**
	 * 
	* @Title: initCorsFilter 
	* @Description: 注册默认的跨域过滤器
	* @param     设定文件 
	* @return void    返回类型 
	* @throws
	 */
	protected void initCorsFilter(ServletContext servletContext) {
		logger.info("AbstractWebBaseApplicationInitializer init CorsFilter start");
		FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", new CorsFilter());
		corsFilter.setAsyncSupported(isAsyncSupported());
		corsFilter.addMappingForUrlPatterns(getDispatcherTypes(), false, "/*");
	}

	protected void initExceptionFilter(ServletContext servletContext) {
		FilterRegistration.Dynamic exceptionFilter = servletContext.addFilter("exceptionFilter", new ExceptionFilter());
		exceptionFilter.setAsyncSupported(isAsyncSupported());
		exceptionFilter.addMappingForUrlPatterns(getDispatcherTypes(), false, "/*");
	}
	
	/**
	 * 
	* @Title: getDispatcherTypes 
	* @Description: 过滤器匹配的请求的类型
	* @param @return    设定文件 
	* @return EnumSet<DispatcherType>    返回类型 
	* @throws
	 */
	protected EnumSet<DispatcherType> getDispatcherTypes() {
		return isAsyncSupported() ?
			EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC) :
			EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE);
	}



}
